#include <iostream>
#include <cassert>
#include <typeinfo>
#include <string>
#include <unistd.h>
#include <any>

// C++17 已经把Any纳入标准库
// 必须在编译阶段使用 -std=c++17 才能使用这个类
// boost库中也实现了 Any
class Any{
public:
    Any()
        :_content(nullptr)
    {}

    template<class T>
    Any(const T& val)
        :_content(new placeholder<T>(val))
    {}

    Any(const Any& other){
        if (other._content){
            _content = other._content->clone();
        }
        else{
            _content = nullptr;
        }
    }

    ~Any(){
        delete _content;
    }

    Any &swap(Any &&other){
        std::swap(_content, other._content);
        return *this;
    }

    // 返回子类对象保存的数据的指针
    template <class T>
    T* get(){
        // 想要获取的数据类型必须和保存的数据类型一致
        assert (typeid(T) == _content->type());
        
        return &((placeholder<T>*)_content)->_val;
    }

    // 赋值运算符的重载函数
    template <class T>
    Any& operator=(const T& val){
        swap(Any(val));
        return *this;
    }

    Any& operator=(const Any& other){
        swap(Any(other));
        return *this;
    }

private:
    class holder{
    public:
        virtual ~holder(){}
        virtual const std::type_info& type() = 0;
        virtual holder * clone() = 0;
    };

    template<class T>
    class placeholder : public holder{
    public:
        placeholder(const T& val)
            :_val(val)
        {}

        // 获取子类对象保存的数据类型
        virtual const std::type_info& type(){
            return typeid(T);
        }

        // 针对当前的对象自身，克隆出一个新的子类对象
        virtual holder * clone(){
            return new placeholder(_val);
        }
    public:
        T _val;
    };

    holder* _content;
};

// 设计一个 Any 类来保存各种不同类型结构的数据，保证传入任何类型的数据，都能通过这个Any类来管理
// 此时的 Any 就是泛型，创建的Any对象可以接收任意类型的参数

class Test{
public:
    Test(){
        std::cout << "构造" << std::endl;
    }

    Test(const Test& t){
        std::cout << "拷贝构造" << std::endl;
    }
    ~Test(){
        std::cout << "析构" << std::endl;
    }
private:
};

int main()
{
    
    std::any a;
    a = 10;
    int* p1 = std::any_cast<int>(&a);
    std::cout << *p1 << std::endl;

    a = std::string("helllllo");
    std::string * ps = std::any_cast<std::string>(&a);
    std::cout << *ps << std::endl;

    // 注意：假设这里只创建了一个Any 对象a
    //       先对a进行赋值，再改变其管理的对象
    // 只有在改变期管理的对象后，才会析构之前的对象

    // Any a;
    // {
    //     Test t;
    //     a = t;
    // }


    // a = 10;
    // int *pa = a.get<int>();
    // std::cout << *pa << std::endl;

    // a = std::string("nihao");

    // std::string *ps = a.get<std::string>();
    // std::cout << *ps << std::endl;

    // while (1)
    // {
    //     sleep(1);
    // }
    

    return 0;
}
